/**
 * 
 */
package yanivosher.aiproject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;


public class GreedyHeuristicAgent extends Agent {

	private LinkedList<Step> optimalPath = null;
	
	public GreedyHeuristicAgent(Vertex currentVertex, Vertex destinationVertex) {
		super(currentVertex, destinationVertex);
	}

	public Step makeAmove(Graph curr) {
		System.out.println("Making a GreedyHeuristicAgent step ");

		if (optimalPath == null) {
			System.out.println("Calculating path");
			calculateGreedyPath();
		}
		if (optimalPath.size() > 0) {
			return optimalPath.removeLast();
		}
		else {
			return new Step(currentVertex, currentVertex, false, false);
		}
	}

	//UNIFORM-COST-SEARCH implementation
	private LinkedList<Step> calculateGreedyPath()
	{
		GraphSearchState initialState = new GraphSearchState(currentVertex, null, Environment.getInstance().graph, this);
		GraphSearchState node = initialState;

		ArrayList<GraphSearchState> exploredSet = new ArrayList<>();
		ArrayList<GraphSearchState> frontier = node.getChildStates();
		Collections.sort(frontier,comperator);
		
		int counter = 0;
		
		while (!node.isStateInGoal()) {
			if (frontier.size()==0) {
				System.err.println("Failure in calculateGreedyPath");
				return null;
			}
			node = frontier.remove(0);
			explorationCost++;
			if (System.getProperty("java.class.path").contains("jar")) {
				System.out.print("\rexploration counter:" + explorationCost);
			}
			//System.out.println("Exploring:" + node.vertex.getId() + " Chems left = " +  node.graph.getChemVertexes().size());
			//System.out.println("After step:" + node.step);
			
			if (node.isStateInGoal()) {
				continue;
			}
			exploredSet.add(node);
			
			for (GraphSearchState childState : node.getChildStates()) {
				if (!exploredSet.contains(childState) && !frontier.contains(childState) ) {
					frontier.add(childState);
				}
				else if (frontier.contains(childState)) {
					GraphSearchState org = frontier.get(frontier.indexOf(childState));
					org.HeuristicCost = Math.min(org.HeuristicCost, childState.HeuristicCost);
				}
			}
			Collections.sort(frontier,comperator);
			//System.out.println("currentState.HeuristicCost:" + node.HeuristicCost);
			
			
			if (counter == 1000) {
				//System.out.println(node.graph.toString());
				counter = 0;
			}
			counter ++;
		}

		optimalPath = new LinkedList<Step>();
		
		while (node.previous != null) {
			optimalPath.add(node.step);
			node = node.previous;
		}
		return optimalPath;
	}

	Comparator<GraphSearchState> comperator = new Comparator<GraphSearchState>() {
		
		@Override
		public int compare(GraphSearchState o1, GraphSearchState o2) {
			if (o1.HeuristicCost > o2.HeuristicCost) {
				return 1;
			}
			else if (o1.HeuristicCost < o2.HeuristicCost) {
				return -1;
			}
			return 0;
		}
	};
	
	@Override
	public boolean idDone() {
		return Environment.getInstance().graph.getChemVertexes().size() == 0;
	}
	
}
